#include "findduplicatesplugin.h"
#include <QAction>
#include <QtPlugin>
#include <QToolBar>
#include <QMultiMap>
#include <QProgressDialog>
#include <QMainWindow>
#include <QApplication>
#include <QFileInfo>
#include "duplicatesdialog.h"
#include <QMessageBox>

Q_EXPORT_PLUGIN2(findduplicatesplugin, FindDuplicatesPlugin)

void FindDuplicatesPlugin::setup(PioCore * core)
{
    m_core = core;
    QToolBar * toolbar = core->toolbar();
    toolbar->addSeparator();
    toolbar->addAction(tr("find duplicates..."), this, SLOT(findDuplicates()));
}

QStringList FindDuplicatesPlugin::licenseInfo()
{
    return QStringList();
}

bool lessSize(MediaItemPtr a, MediaItemPtr b)
{
    QFileInfo fia(a->metadata().filename);
    QFileInfo fib(b->metadata().filename);
    return fia.size() < fib.size();
}

void FindDuplicatesPlugin::findDuplicates()
{
    m_core->mainwindow()->setEnabled(false);

    QList<MediaItemPtr> items = m_core->all();
    qSort(items.begin(), items.end(), lessSize);

    QList<QSet<MediaItemPtr> > groups;

    int n = items.size() - 1;
    QProgressDialog progress(tr("Find duplicates..."), tr("Cancel"), 0, n, m_core->mainwindow());

    for(int i=0; i<items.size() - 1; i++) {
        MediaItemPtr a = items[i];
        MediaItemPtr b = items[i+1];
        QFileInfo fia(a->metadata().filename);
        QFileInfo fib(b->metadata().filename);
        if(fia.size() == fib.size()) {
            if(equal(a->metadata().filename, b->metadata().filename)) {
                int group = -1;
                for(int j=0; j<groups.size(); j++) {
                    if(groups[j].contains(a) || groups[j].contains(b)) {
                        if(group >= 0) {
                            groups[group].unite(groups[j]);
                            groups.removeAt(j);
                            j--;
                        }
                        else {
                            group = j;
                            groups[j].insert(a);
                            groups[j].insert(b);
                        }
                    }
                }
                if(group < 0) {
                    groups.append(QSet<MediaItemPtr>() << a << b);
                }
                progress.setLabelText(QString(tr("Find duplicates... (%1 groups found)")).arg(groups.size()));
            }
        }
        progress.setValue(progress.value()+1);
        qApp->processEvents();
        if(progress.wasCanceled()) {
            m_core->mainwindow()->setEnabled(true);
            return;
        }
    }
    m_core->mainwindow()->setEnabled(true);
    progress.close();
    if(groups.isEmpty())
        QMessageBox::information(m_core->mainwindow(), tr("Find duplicates..."), tr("No duplicates found!"));
    else {
        DuplicatesDialog d(m_core, groups, m_core->mainwindow());
        d.exec();
    }
}

bool FindDuplicatesPlugin::equal(const QString & filea, const QString & fileb)
{
    QFile fa(filea);
    QFile fb(fileb);
    if(!fa.open(QFile::ReadOnly) || !fb.open(QFile::ReadOnly))
        return false;
    while(!fa.atEnd() && !fb.atEnd()) {
        QByteArray a = fa.read(1024);
        QByteArray b = fb.read(1024);
        if(a != b)
            return false;
    }
    return true;
}
